package com.zx.JDK特性.jdk1_8;

import com.zx.JDK特性.jdk1_8.interD.InterfaceDemo2;
import com.zx.common.entity.User;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.Test;

/**
 * Lambda表达式的函数式接口
 */
public class Lambda3 {

    /**
     * Consumer<T> :消费型接口
     * void accept(T t);
     *
     * Supplier<T> :供给型接口
     * T get();
     *
     * Function<T,R> :函数型接口
     * R apply(T t);
     *
     * Predicate<T> :断言型接口
     * boolean test(T t);
     */

    List<User> list = Arrays.asList(
            new User(2L, "222", 20),
            new User(4L, "444", 40),
            new User(4L, "455", 40),
            new User(5L, "555", 50),
            new User(3L, "333", 30),
            new User(1L, "111", 10)
    );

    public static String getValue(final String str, final InterfaceDemo2 fun) {
        return fun.run(str);
    }

    public static <T> BigDecimal sum(final List<T> list, final Calculator<T, ? extends BigDecimal> mapper) {
        BigDecimal sum = BigDecimal.ZERO;
        for (final T t : list) {
            final BigDecimal apply = mapper.apply(t);
            sum = sum.add(apply);
        }
        return sum;
    }

    /**
     * 需求2：
     * 1.声明函数式接口，接口中声明抽象方法，public String getvalue(String str);
     * 2.声明类InterfaceDemo2，类中编写方法使用接口作为参数，讲一个字符串转换成大写，并作为方法的返回值。
     */
    @Test
    public static void test02() {
        final String value = Lambda3.getValue("abcd", x -> x.toUpperCase());
        System.out.println(value);
    }

    /**
     * @Title: 需求3：对金额进行就和
     * @date: 2020-8-3015:03:20
     * @author: zhangxue
     */
    @Test
    public static void test03() {
        final List<Account> list = Arrays.asList(
                new Account("111", BigDecimal.TEN),
                new Account("222", BigDecimal.TEN),
                new Account("333", BigDecimal.TEN),
                new Account("444", BigDecimal.TEN)
        );
        // 自定义方法
        final BigDecimal sum = Lambda3.sum(list, Account::getAmount);
        System.out.println(sum);

        // JDK方法
        final BigDecimal reduce = list.stream().map(Account::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println(reduce);
    }

    /**
     * 需求1：lambda表达式的使用:
     * 调用Collections.sort方法，通过定制排序比较两个user（先按年龄比较，年龄相同按姓名比）
     */
    @Test
    public void test01() {
        Collections.sort(this.list, (x, y) -> {
            final Integer age1 = x.getAge();
            final Integer age2 = y.getAge();
            if (age1.intValue() == age2.intValue()) {//先按年龄比较，年龄相同按姓名比
                return x.getName().compareTo(y.getName());
            } else {
                return Integer.compare(age1, age2);
            }
        });
        this.list.forEach(x -> System.out.println(x));
    }

    private interface Calculator<T, R> {

        R apply(T t);
    }

    @Data
    @AllArgsConstructor
    private static class Account {

        private String accountId;
        private BigDecimal amount;
    }


}
